using System;
using System.Collections.Generic;
using System.Linq;

using Csla;

using EntModApp.EntServices.Business;
using EntModApp.EntServices.IoC;

using DemoApp.DataAccess;

namespace DemoApp.BusinessLayer 
{
  [Serializable]
  public partial class CslaSubjectEditCollection
    : BusinessListBase<CslaSubjectEditCollection, CslaSubjectEdit>,
    IBusinessObjectCollection<ISubject>
  {
    #region [ Business Properties ]

    public int TotalItems { get; private set; }

    #endregion [ Business Properties ]

    #region [ Factory Methods ]

    #region [ Root Factory Methods ]
    public static CslaSubjectEditCollection New()
    {
      return DataPortal.Create<CslaSubjectEditCollection>();
    }

    public static CslaSubjectEditCollection GetSubjectEditById(Guid SubjectId, SubjectLoadSettings loadSettings = null)
    {
      return GetSubjectEditById(new SubjectKey { SubjectId = SubjectId }, loadSettings);
    }

    public static CslaSubjectEditCollection GetSubjectEditById(SubjectKey key, SubjectLoadSettings loadSettings = null)
    {
      if (key == null) throw new ArgumentNullException("key");
      loadSettings = SubjectLoadSettings.FromSubjectLoadSettings(loadSettings);
      loadSettings.Filter.ByKey = key;
      var criteria = new GetAllCriteria
      {
        LoadSettings = loadSettings,
      };
      var result = DataPortal.Fetch<CslaSubjectEditCollection>(criteria);
      return result;
    }

    public static CslaSubjectEditCollection GetSubjectEditCollection(SubjectLoadSettings loadSettings = null)
    {
      loadSettings = SubjectLoadSettings.FromSubjectLoadSettings(loadSettings);
      var criteria = new GetAllCriteria
      {
        LoadSettings = loadSettings,
      };
      var result = DataPortal.Fetch<CslaSubjectEditCollection>(criteria);
      return result;
    }
    #endregion [ Root Factory Methods ]

    #region [ Child Factory Methods ]
    internal static CslaSubjectEditCollection GetSubjectEditCollection(IEnumerable<Subject> data, SubjectLoadSettings loadSettings)
    {
      if (data == null) throw new ArgumentNullException("data");
      if (loadSettings == null) throw new ArgumentNullException("loadSettings");
      var result = new CslaSubjectEditCollection();
      result.MarkAsChild();
      result.FetchAll(data, loadSettings);
      result.TotalItems = result.Count;
      return result;
    }
    #endregion [ Child Factory Methods ]

    private static int ForceInit = 0;
    protected CslaSubjectEditCollection()
    {
      ForceInit = 1;
    }

    #region [ Criterias ]
    [Serializable]
    class GetAllCriteria : CriteriaBase<GetAllCriteria>
    {
      public SubjectLoadSettings LoadSettings { get; set; }
    }
    #endregion

    #endregion

    #region [ Data Access ]
    private void DataPortal_Fetch(GetAllCriteria criteria)
    {
      var dbFactory = ServiceLocator.Current.GetInstance<IDemoAppModelDataRepositoryFactory>();
      IEnumerable<Subject> data;
      using (var db = dbFactory.CreateRepository())
      {
        int total;
        data = db.Subjects.Retrieve(criteria.LoadSettings, out total);
        TotalItems = total;
      }
      FetchAll(data, criteria.LoadSettings);
    }

    private void FetchAll(IEnumerable<Subject> data, SubjectLoadSettings loadSettings)
    {
      var oldRaiseListChangedEvents = RaiseListChangedEvents;
      try
      {
        RaiseListChangedEvents = false;

        foreach (var item in data)
        {
          var element = CslaSubjectEdit.GetSubjectEdit(item, loadSettings);
          this.Add(element);
        }
      }
      finally
      {
        RaiseListChangedEvents = oldRaiseListChangedEvents;
      }
    }
    #endregion

    #region [ Explicit IBusinessObjectCollection<ISubject> implementation ]

    void ICollection<ISubject>.Add(ISubject item)
    {
      this.Add((CslaSubjectEdit)item);
    }

    void ICollection<ISubject>.Clear()
    {
      this.Clear();
    }

    bool ICollection<ISubject>.Contains(ISubject item)
    {
      return this.Contains((CslaSubjectEdit)item);
    }

    void ICollection<ISubject>.CopyTo(ISubject[] array, int arrayIndex)
    {
      int size = Math.Min(array.Length - arrayIndex, this.Count);
      if (size > 0)
      {
        var a = new CslaSubjectEdit[size];
        this.CopyTo(a, 0);
        Array.Copy(a, 0, array, arrayIndex, size);
      }
    }

    int ICollection<ISubject>.Count
    {
      get { return this.Count; }
    }

    bool ICollection<ISubject>.IsReadOnly
    {
      get { return false; }
    }

    bool ICollection<ISubject>.Remove(ISubject item)
    {
      return this.Remove((CslaSubjectEdit)item);
    }

    IEnumerator<ISubject> IEnumerable<ISubject>.GetEnumerator()
    {
      return this.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
      return this.GetEnumerator();
    }

    bool IBusinessObject.IsReadonly
    {
      get { return false; }
    }

    bool IBusinessObject.IsDirty
    {
      get { return this.IsDirty; }
    }

    ISubject IBusinessObjectCollection<ISubject>.this[int index]
    {
      get
      {
        return this[index];
      }
      set
      {
        this[index] = (CslaSubjectEdit)value;
      }
    }

    #endregion [ Explicit IBusinessObjectCollection<ISubject> implementation ]
  }
}
